#第二十章 属性描述符

#描述符类 用于托管类的属性
class Quantity():
    def __init__(self,storage_name):
        self.storage_name = storage_name

    def __set__(self,instance,value): #作为某个实例或者类属性时 被赋值 会先执行该函数
        if value<=0:
            raise ValueError('值必须大于0')
        instance.__dict__[self.storage_name] = value #修改被托管实例的属性 实际也是想要这样的效果

    def __get__(self,instance,cls): #作为某个实例或者类属性时 被访问 会先执行该函数
        print("__get__ instance,cls=",instance,cls)
        return instance.__dict__[self.storage_name]
    def foo(self,*arg):
        print('arg=',arg)
    
class LineItem():
    weight = Quantity("weight")
    price = Quantity("price")

    def __init__(self,description,weight,price):
        self.description = description        
        # self.weight 首先访问自身有没有属性 没有就访问类属性 类属性是一个 Quantity 实例 为实例赋值会执行类方法 __set__
        self.weight = weight 
        self.price = price

    def subtotal(self):
        return self.weight * self.price

truffle = LineItem('White truffle', 110,10)
print('truffle.weight',truffle.weight)